#!/usr/bin/env node

// 使用动态导入支持ES模块
let ora;
(async () => {
    ora = (await import('ora')).default;
    
    const fs = require('fs').promises; // 导入文件系统模块
    const path = require('path'); // 导入路径模块
    const { execSync } = require('child_process'); // 导入子进程模块

    /**
     * React脚手架创建器
     * 演示ora在真实脚手架场景中的应用
     */
    class ReactScaffold {
        constructor(projectName) {
            this.projectName = projectName; // 项目名称
            this.projectPath = path.resolve(projectName); // 项目路径
            this.mainSpinner = null; // 主进度条
        }

        /**
         * 开始创建React项目
         */
        async create() {
            console.log(`🚀 开始创建React项目: ${this.projectName}\n`);
            
            try {
                // 初始化主进度条
                this.mainSpinner = ora('正在初始化项目环境...').start();
                
                // 检查环境
                await this.checkEnvironment();
                
                // 创建项目目录
                await this.createProjectDirectory();
                
                // 初始化package.json
                await this.initializePackageJson();
                
                // 创建项目结构
                await this.createProjectStructure();
                
                // 创建基础文件
                await this.createBaseFiles();
                
                // 安装依赖
                await this.installDependencies();
                
                // 初始化Git仓库
                await this.initializeGit();
                
                // 完成
                this.mainSpinner.succeed(`✅ React项目 "${this.projectName}" 创建完成！`);
                this.showSuccessMessage();
                
            } catch (error) {
                this.mainSpinner.fail(`❌ 项目创建失败: ${error.message}`);
                console.error('\n详细错误信息:', error);
                process.exit(1);
            }
        }

        /**
         * 检查开发环境
         */
        async checkEnvironment() {
            this.mainSpinner.text = '正在检查Node.js环境...';
            await this.sleep(500);
            
            // 检查Node.js版本
            const nodeVersion = process.version;
            const majorVersion = parseInt(nodeVersion.slice(1).split('.')[0]);
            
            if (majorVersion < 14) {
                throw new Error(`Node.js版本过低，需要14.0.0或更高版本，当前版本: ${nodeVersion}`);
            }
            
            this.mainSpinner.text = '正在检查npm环境...';
            await this.sleep(300);
            
            // 检查npm版本
            try {
                const npmVersion = execSync('npm --version', { encoding: 'utf8' }).trim();
                console.log(`   📦 npm版本: ${npmVersion}`);
            } catch (error) {
                throw new Error('npm未安装或无法访问');
            }
            
            this.mainSpinner.text = '正在检查项目名称...';
            await this.sleep(200);
            
            // 检查项目名称是否合法
            if (!/^[a-zA-Z0-9-_]+$/.test(this.projectName)) {
                throw new Error('项目名称只能包含字母、数字、连字符和下划线');
            }
            
            // 检查目录是否已存在
            try {
                await fs.access(this.projectPath);
                throw new Error(`目录 "${this.projectName}" 已存在，请选择其他名称`);
            } catch (error) {
                if (error.code !== 'ENOENT') {
                    throw error;
                }
            }
        }

        /**
         * 创建项目目录
         */
        async createProjectDirectory() {
            this.mainSpinner.text = '正在创建项目根目录...';
            
            try {
                await fs.mkdir(this.projectPath, { recursive: true });
                await this.sleep(300);
            } catch (error) {
                throw new Error(`无法创建项目目录: ${error.message}`);
            }
        }

        /**
         * 初始化package.json
         */
        async initializePackageJson() {
            this.mainSpinner.text = '正在初始化package.json...';
            
            const packageJson = {
                name: this.projectName,
                version: '0.1.0',
                private: true,
                description: `使用脚手架创建的React应用: ${this.projectName}`,
                main: 'index.js',
                scripts: {
                    start: 'react-scripts start',
                    build: 'react-scripts build',
                    test: 'react-scripts test',
                    eject: 'react-scripts eject',
                    lint: 'eslint src --ext .js,.jsx,.ts,.tsx',
                    format: 'prettier --write "src/**/*.{js,jsx,ts,tsx,json,css,scss,md}"'
                },
                dependencies: {
                    react: '^18.2.0',
                    'react-dom': '^18.2.0',
                    'react-scripts': '5.0.1',
                    'web-vitals': '^2.1.4'
                },
                devDependencies: {
                    '@testing-library/jest-dom': '^5.16.4',
                    '@testing-library/react': '^13.3.0',
                    '@testing-library/user-event': '^13.5.0',
                    eslint: '^8.15.0',
                    'eslint-config-react-app': '^7.0.0',
                    prettier: '^2.6.2'
                },
                browserslist: {
                    production: [
                        '>0.2%',
                        'not dead',
                        'not op_mini all'
                    ],
                    development: [
                        'last 1 chrome version',
                        'last 1 firefox version',
                        'last 1 safari version'
                    ]
                }
            };
            
            try {
                await fs.writeFile(
                    path.join(this.projectPath, 'package.json'),
                    JSON.stringify(packageJson, null, 2),
                    'utf8'
                );
                await this.sleep(200);
            } catch (error) {
                throw new Error(`无法创建package.json: ${error.message}`);
            }
        }

        /**
         * 创建项目目录结构
         */
        async createProjectStructure() {
            this.mainSpinner.text = '正在创建项目目录结构...';
            
            const directories = [
                'src',
                'src/components',
                'src/pages',
                'src/hooks',
                'src/utils',
                'src/assets',
                'src/assets/images',
                'src/assets/styles',
                'public'
            ];
            
            for (const dir of directories) {
                try {
                    await fs.mkdir(path.join(this.projectPath, dir), { recursive: true });
                    await this.sleep(50);
                } catch (error) {
                    throw new Error(`无法创建目录 ${dir}: ${error.message}`);
                }
            }
        }

        /**
         * 创建基础文件
         */
        async createBaseFiles() {
            this.mainSpinner.text = '正在创建基础文件...';
            
            const files = [
                {
                    name: 'public/index.html',
                    content: this.generateIndexHtml()
                },
                {
                    name: 'src/index.js',
                    content: this.generateIndexJs()
                },
                {
                    name: 'src/App.js',
                    content: this.generateAppJs()
                },
                {
                    name: 'src/App.css',
                    content: this.generateAppCss()
                },
                {
                    name: 'src/index.css',
                    content: this.generateIndexCss()
                },
                {
                    name: 'README.md',
                    content: this.generateReadme()
                },
                {
                    name: '.gitignore',
                    content: this.generateGitignore()
                },
                {
                    name: '.eslintrc.js',
                    content: this.generateEslintConfig()
                },
                {
                    name: '.prettierrc',
                    content: this.generatePrettierConfig()
                }
            ];
            
            for (let i = 0; i < files.length; i++) {
                const file = files[i];
                this.mainSpinner.text = `正在创建文件: ${file.name} (${i + 1}/${files.length})`;
                
                try {
                    const filePath = path.join(this.projectPath, file.name);
                    const dir = path.dirname(filePath);
                    
                    // 确保目录存在
                    await fs.mkdir(dir, { recursive: true });
                    
                    // 写入文件
                    await fs.writeFile(filePath, file.content, 'utf8');
                    await this.sleep(100);
                } catch (error) {
                    throw new Error(`无法创建文件 ${file.name}: ${error.message}`);
                }
            }
        }

        /**
         * 安装依赖
         */
        async installDependencies() {
            this.mainSpinner.text = '正在安装项目依赖...';
            
            try {
                // 切换到项目目录
                process.chdir(this.projectPath);
                
                // 使用npm install安装依赖
                this.mainSpinner.text = '正在解析依赖关系...';
                await this.sleep(1000);
                
                this.mainSpinner.text = '正在下载依赖包...';
                await this.sleep(2000);
                
                this.mainSpinner.text = '正在构建依赖...';
                await this.sleep(1500);
                
                // 这里可以实际执行npm install
                // execSync('npm install', { stdio: 'pipe' });
                
                this.mainSpinner.text = '正在验证安装...';
                await this.sleep(500);
                
            } catch (error) {
                throw new Error(`依赖安装失败: ${error.message}`);
            }
        }

        /**
         * 初始化Git仓库
         */
        async initializeGit() {
            this.mainSpinner.text = '正在初始化Git仓库...';
            
            try {
                // 检查是否在项目目录中
                if (process.cwd() !== this.projectPath) {
                    process.chdir(this.projectPath);
                }
                
                // 初始化Git仓库
                execSync('git init', { stdio: 'pipe' });
                await this.sleep(300);
                
                // 添加所有文件到Git
                execSync('git add .', { stdio: 'pipe' });
                await this.sleep(200);
                
                // 创建初始提交
                execSync('git commit -m "Initial commit: React project scaffold"', { stdio: 'pipe' });
                await this.sleep(200);
                
            } catch (error) {
                // Git初始化失败不是致命错误，只显示警告
                this.mainSpinner.warn('⚠️ Git仓库初始化失败，但项目创建成功');
            }
        }

        /**
         * 显示成功消息
         */
        showSuccessMessage() {
            console.log('\n🎉 恭喜！您的React项目已成功创建！');
            console.log('\n📁 项目结构：');
            console.log(`   ${this.projectName}/`);
            console.log('   ├── public/');
            console.log('   │   └── index.html');
            console.log('   ├── src/');
            console.log('   │   ├── components/');
            console.log('   │   ├── pages/');
            console.log('   │   ├── hooks/');
            console.log('   │   ├── utils/');
            console.log('   │   ├── assets/');
            console.log('   │   ├── App.js');
            console.log('   │   ├── App.css');
            console.log('   │   ├── index.js');
            console.log('   │   └── index.css');
            console.log('   ├── package.json');
            console.log('   ├── README.md');
            console.log('   └── .gitignore');
            
            console.log('\n🚀 开始开发：');
            console.log(`   cd ${this.projectName}`);
            console.log('   npm start');
            
            console.log('\n📚 有用的命令：');
            console.log('   npm start     - 启动开发服务器');
            console.log('   npm run build - 构建生产版本');
            console.log('   npm test      - 运行测试');
            console.log('   npm run lint  - 代码检查');
            console.log('   npm run format - 代码格式化');
        }

        /**
         * 工具函数：延迟执行
         */
        sleep(ms) {
            return new Promise(resolve => setTimeout(resolve, ms));
        }

        // 文件内容生成方法
        generateIndexHtml() {
            return `<!DOCTYPE html>
<html lang="zh-CN">
  <head>
    <meta charset="utf-8" />
    <link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <meta name="theme-color" content="#000000" />
    <meta name="description" content="使用脚手架创建的React应用" />
    <title>${this.projectName}</title>
  </head>
  <body>
    <noscript>您需要启用JavaScript才能运行此应用。</noscript>
    <div id="root"></div>
  </body>
</html>`;
        }

        generateIndexJs() {
            return `import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
import App from './App';

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>
);`;
        }

        generateAppJs() {
            return `import React from 'react';
import './App.css';

function App() {
  return (
    <div className="App">
      <header className="App-header">
        <h1>欢迎使用 ${this.projectName}!</h1>
        <p>这是一个使用脚手架创建的React应用。</p>
        <a
          className="App-link"
          href="https://reactjs.org"
          target="_blank"
          rel="noopener noreferrer"
        >
          学习React
        </a>
      </header>
    </div>
  );
}

export default App;`;
        }

        generateAppCss() {
            return `.App {
  text-align: center;
}

.App-header {
  background-color: #282c34;
  padding: 20px;
  color: white;
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  font-size: calc(10px + 2vmin);
}

.App-link {
  color: #61dafb;
  text-decoration: none;
}

.App-link:hover {
  text-decoration: underline;
}`;
        }

        generateIndexCss() {
            return `body {
  margin: 0;
  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
    'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
    sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

code {
  font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',
    monospace;
}`;
        }

        generateReadme() {
            return `# ${this.projectName}

这是一个使用脚手架创建的React应用。

## 开始使用

在项目目录中运行：

\`\`\`bash
npm start
\`\`\`

应用将在 [http://localhost:3000](http://localhost:3000) 中打开。

## 可用的脚本

在项目目录中，您可以运行：

### \`npm start\`

在开发模式下运行应用。
打开 [http://localhost:3000](http://localhost:3000) 在浏览器中查看。

### \`npm test\`

以交互式观察模式启动测试运行器。

### \`npm run build\`

将生产应用程序构建到 \`build\` 文件夹。

### \`npm run eject\`

**注意：这是单向操作。一旦您 \`eject\`，您就无法返回！**

如果您对构建工具和配置选择不满意，您可以随时 \`eject\`。此命令将从项目中删除单个构建依赖项。

## 了解更多

要了解React，请查看 [React文档](https://reactjs.org/)。`;
        }

        generateGitignore() {
            return `# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.

# dependencies
/node_modules
/.pnp
.pnp.js

# testing
/coverage

# production
/build

# misc
.DS_Store
.env.local
.env.development.local
.env.test.local
.env.production.local

npm-debug.log*
yarn-debug.log*
yarn-error.log*`;
        }

        generateEslintConfig() {
            return `module.exports = {
  extends: ['react-app'],
  rules: {
    'no-console': 'warn',
    'no-unused-vars': 'warn',
  },
};`;
        }

        generatePrettierConfig() {
            return `{
  "semi": true,
  "trailingComma": "es5",
  "singleQuote": true,
  "printWidth": 80,
  "tabWidth": 2
}`;
        }
    }

    // 命令行参数处理
    function parseArguments() {
        const args = process.argv.slice(2);
        
        if (args.length === 0) {
            console.error('❌ 请提供项目名称');
            console.log('用法: node create-react-app.js <项目名称>');
            process.exit(1);
        }
        
        return args[0];
    }

    // 主函数
    async function main() {
        const projectName = parseArguments();
        const scaffold = new ReactScaffold(projectName);
        
        try {
            await scaffold.create();
        } catch (error) {
            console.error('脚手架创建失败:', error.message);
            process.exit(1);
        }
    }

    // 如果直接运行此脚本，则执行主函数
    if (require.main === module) {
        main();
    }

    module.exports = { ReactScaffold };
})(); 